package com.djnt.catering;

import java.lang.reflect.Field;
import java.util.ArrayList;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.util.Log;

public class Marshal {
	private static final String TAG = "Marshal";

	static {
		try {
			System.loadLibrary("catering_jni");
		} catch (UnsatisfiedLinkError ule) {
			Log.e(TAG, "Could not load native library");
		}
	}

	/**
	 * A callback interface for a custom sqlite3 function. This can be used to
	 * create a function that can be called from sqlite3 database triggers.
	 * 
	 * @hide
	 */
	public interface CustomFunction {
		public void callback(String[] args);
	}

	public Marshal(Context context) {
		// TODO Auto-generated constructor stub
	}

	/**
	 * Registers a CustomFunction callback as a function that can be called from
	 * sqlite3 database triggers.
	 * 
	 * @param name
	 *            the name of the sqlite3 function
	 * @param numArgs
	 *            the number of arguments for the function
	 * @param function
	 *            callback to call when the function is executed
	 * @hide
	 */
	public void addCustomFunction(SQLiteDatabase db, String name, int numArgs,
			CustomFunction function) {
		try {
			verifyDbIsOpen(db);
			synchronized (mCustomFunctions) {
				int ref = native_addCustomFunction(getNativeHandle(db), name,
						numArgs, function);
				if (ref != 0) {
					// save a reference to the function for cleanup later
					mCustomFunctions.add(new Integer(ref));
				} else {
					throw new SQLiteException("failed to add custom function "
							+ name);
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void verifyDbIsOpen(SQLiteDatabase db) {
		// TODO Auto-generated method stub

	}

	private void releaseCustomFunctions(SQLiteDatabase db) {
		try {
			synchronized (mCustomFunctions) {
				for (int i = 0; i < mCustomFunctions.size(); i++) {
					Integer function = mCustomFunctions.get(i);
					native_releaseCustomFunction(getNativeHandle(db),
							function.intValue());
				}
				mCustomFunctions.clear();
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	// list of CustomFunction references so we can clean up when the database
	// closes
	private final ArrayList<Integer> mCustomFunctions = new ArrayList<Integer>();

	private native void native_releaseCustomFunction(int i, int function);

	native int native_addCustomFunction(int i, String name,
			int mNativeHandle, CustomFunction function);

	native void native_addCustomFunctions(int mNativeHandle);

	public void addCustomFunctions(SQLiteDatabase db) {
		try {
			int mNativeHandle = getNativeHandle(db);
			// Log.d(TAG, "SQLiteDatabase.mNativeHandle = " + mNativeHandle);
			native_addCustomFunctions(mNativeHandle);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static int getNativeHandle(SQLiteDatabase db)
			throws IllegalArgumentException, IllegalAccessException,
			SecurityException, NoSuchFieldException {
		// TODO Auto-generated method stub
		Class<? extends SQLiteDatabase> cls = db.getClass();
		/*
		 * Field[] fs = cls.getDeclaredFields(); for (Field a : fs) { Log.d(TAG,
		 * "" + a); }
		 */

		Field f = cls.getDeclaredField("mNativeHandle");
		f.setAccessible(true);
		return f.getInt(db);
	}

	public void releaseCustomFunction() {
		// TODO Auto-generated method stub

	}

}
